Retina, 45 43 bytes
Byte count assumes ISO 8859-1 encoding.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
The leading linefeed is significant. Input and output are linefeed-terminated lists of printable ASCII strings (note that both have a single trailing linefeed).
Try it online!
I knew for a while that transposing rectangular blocks would be a pain in Retina (whereas transposing squares isn't too bad), but never actually tried. The first solution was indeed a whopping 110 bytes long, but after several substantial changes in the approach, the resulting 45 bytes are by far not as bad as I suspected (but still...). Explanation will follow tomorrow.
Explanation
Stage 1: Sort
O$#`.(?<=(.+))|¶
$.1
This does the main work of reordering the characters in the input, but it ends up messing up the separation into lines. Interestingly, if we remove the |¶, we get the code required to transpose a square input.
Sort stages (denoted by the O) work like this: they find all matches of the given regex (the thing after the `), and then sort those matches and reinsert them into the places where the matches were found. As it happens, this regex matches every single character: non-linefeeds via the .(?<=(.*)) alternative and linefeeds via the ¶. Hence, it sorts all characters in the input. The more interesting part is what they are sorted by.
The $ option activates a "sort-by" mode, where each match is replaced with the substitution pattern on the second line, which is then used for comparing the matches. Furthermore, the # tells Retina to convert the result of the substitution to an integer, and compare those integers (instead of treating them as strings).
So finally, we need to look at the regex and the substitution. If the first alternative matches (i.e. we have matched any character within one of the lines), then the (?<=(.*)) captures everything up to that character on that line into group 1. The $.1 in the substitution pattern replaces this with the length of group 1. Hence, the first character in each string becomes 1, the second becomes 2, the third becomes 3 and so on. It should be clear now how this transposes a square input: all the first characters of the lines come first and all end up in the top-most line, then all the second characters end up in the second line and so on. But for these rectangular inputs, we're also matching the linefeeds. Since group 1 is unused in this case, the substitution is empty, but for the purposes of the # option, this is considered 0. That means, all the linefeeds are sorted to the front.
So now we do have the characters in the first order (first character of each string, second character of each string, etc.) and all the linefeeds at the start.
Stage 2: Match
!`(?<=(¶)+.*)(?<-1>.)+
We now need to split up the characters into lines of the correct length. This length corresponds to the number of lines in the original input, which is corresponds to the number of linefeeds we have at the beginning of the string.
The splitting is done here with the help of a match stage, which simply finds all matches of the given regex and uses the ! option to print those matches (the default would be to count them instead). So the goal of the regex is to match one line at a time.
We start by "counting" the number with the lookbehind (?<=(¶)*.*). It generates one capture in group 1 for every linefeed at the front.
Then, for each of those captures, we match a single character with (?<-1>.)+.