Видны две ошибки. Первая не должна влиять на результат, но может привести к выходу индекса за границу массива:
if ((i < leftLen && left[i] < right[j]) || j >= rightLen) {
В случае, когда j==rightLen, у вас будет проверяться элемент right[j]. Условия здесь надо поменять местами:
if ( j >= rightLen || (i < leftLen && left[i] < right[j])) {
Вторая - что элемент array[mid] не будет участвовать ни в первом, ни во втором рекурсивных вызовах mergeSort. Второй вызов надо было сделать
mergeSort(array, mid, end);
А чтобы не было бесконечной рекурсии, изменить условие в mergeSort на
if (start < end-1) {
(или на if(start < mid) ).
Ну, и в классическом С невозможна конструкция
int leftLen = mid - start,
left[leftLen];
Там массивы могут быть только фиксированной длины, а для динамического захвата приходится использовать malloc. Но если компилируется, значит, ваша версия компилятора такое позволяет.
UPD. В С99 действительно возможны массивы переменной длины, и пишут, что gcc их поддерживает. Ну и ладно. Visual Studio такое не позволяет.