R, 137 126 bytes
\(a,b,`!`=nchar,y=`if`((!b)>!a,c(a,b),c(b,a)),x=strsplit(y,""))Reduce(paste0,Map(max,names(Map(c,el(x),u<-x[[2]])),u,na.rm=T)) My answer to this challenge is the largest one because R has default vector recycling. The code's key piece is the call Map(max,a,b), where a and b are characters vectors. This outputs the list of characters with a larger value - similar to the other solutions here.
But that works only on the strings with the same size. If the strings are of different length, than the shortest one is "recycled", meaning that the missing elements are added from the beginning of the same vector. For example, strings "a.....b" and "..c......." will be merged to "a.c...ba.." instead of "a.c...b...".
As far as I know, it is impossible to deactivate vector recycling in vector-operating functions like Map, rbind, paste etc. Luckily, I have noticed that names adds NAs to the end if the names vector is shorter than the host. Now that the shortest vector has the proper length, it could be passed to max function with na.rm=TRUE filter, which removes NAs.
Finally, there is a statement y=`if`((!b)>!a,c(a,b),c(b,a)) which is choosing the shortest string and puts it to the first place, so that it will be properly converted with the names as shown above.
Other notable tricks used here:
Reduce(paste0,x), 16 bytes instead ofpaste0(x,collapse=""), 21 bytesel(x), 5 bytes instead ofx[[1]], 6 bytes.
Vanilla version - R, 122 bytes
Employs a for cycle.
\(a,b,`!`=nchar,x=strsplit(c(a,b),""),d={}){for(j in 1:max(!a,!b))d=Reduce(paste0,c(d,max(el(x)[j],x[[2]][j],na.rm=T)));d}