How to write a generic list<t> method that will cast at runtime?

You can't cast ANY to a more specific type, so you have to actually obtain the type that you want to return. Without proper reflection, you have to tell the function what type you'd like to return. There's several ways you can do that, but here's one way:

public class Parser {
    public static List<List<Object>> splitList(List<Object> items, Integer splitSize, Type destType) {
        // Take our destination type and cast to generic
        List<List<Object>> result = (List<List<Object>>)destType.newInstance();
        // Get a copy of source list to obtain list type.
        List<Object> protoList = items.clone();
        protoList.clear();
        // This is the list that will actually be added to result
        List<Object> tempList = protoList.clone();
        // A for loop with two counters.
        Integer index = 0, count = 0, size = items.size();
        while(index < size) {
            tempList.add(items[index++]);
            count++;
            // Split size reached, add to result and make new list
            if(count == splitSize) {
                result.add(tempList);
                tempList = protoList.clone();
                count = 0;
            }
        }
        // Add left-over partial
        if(!tempList.isEmpty()) {
            result.add(protoList);
        }
        return result;
    }
}

You use the code like this:

List<List<String>> v = 
    (List<List<String>>)Parser.splitList(
        myStringList,
        5, List<List<String>>.class
    );

It's a little messy, as you have to give it a primitive data type and then cast it back, but it works.

As an alternative, you might try the "out-param" approach:

public class Parser {
    public static void splitList(List<Object> items, Integer splitSize, List<List<Object>> result) {
        List<Object> protoList = items.clone();
        protoList.clear();
        List<Object> tempList = protoList.clone();
        Integer index = 0, count = 0, size = items.size();
        while(index < size) {
            tempList.add(items[index++]);
            count++;
            if(count == splitSize) {
                result.add(tempList);
                tempList = protoList.clone();
                count = 0;
            }
        }
        if(!tempList.isEmpty()) {
            result.add(tempList);
        }
    }
}

This one can't incur the run-time exception if destType isn't compatible with List<List<Object>> and saves you a bit of casting. You can use it like this:

List<List<String>> v = new List<List<String>>();
Parser.splitList(myStringList, 5, v);

The callee now becomes responsible for initializing the correct object type, but avoids the extra casting.