Накидал пример (там с forEach, но при желании можно переписать):
function f(length, from, to){
return getResult( --length, from, to, getArray( from, to ) );
function getResult(length, from, to, result){
var newResult = [];
getArray( from, to ).forEach(function(x){
result.forEach(function(y){
newResult.push( x.concat( y ) );
});
});
if( --length > 0 ) return getResult(length, from, to, newResult);
return newResult;
};
function getArray(from, to){
for(var array = []; from <= to; from++)
array.push([ from ]);
return array;
};
};
alert(
f( 3, 4, 5 ).join("\n")
);
// Твой вариант f( 15, 1, 15 );
Конечно, браузер сдохнет столько вариантов считать, но алгоритм - рабочий)