Данный вариант не претендует на лучший
Это пример подхода
<script>
const combinator = matrix => matrix.reduceRight((prev, current) => {
var result = []
current.forEach(a => prev.forEach(b => result.push([a].concat(b))))
return result
})
const arr = [1, 2, 3, 4]
const data = (new Array(4)).fill(arr)
const result = combinator(data)
.filter(v => !/(\d).*\1+/.test(v.join('')) && (v[0] < 2 || (v[0] === 2 && v[1] < 4)))
.map(([a, b, c, d]) => `${a}${b}:${c}${d}`)
document.write(JSON.stringify(result))
</script>