Many reasons are affected to your result i try to explain some important of :
At First it's important to know how config your VMs many options are important like : reserved CPU ? Or reserve Memory Or Share it.
How many Vms in your host and when you run your queries how many workloads your host has ? and many other reason like hypervisor config hypervisor queue and etc ...
Of course it's too complex for explaining by few rows you can read this:
Cardinality Estimation (CE)
After SQL Server 2012 CE is Change and use new algorithm it's one of most factor you have to pay attention when you want to check SQL Server 2012 Vs SQL Server 2016
But I explain about some important factor in SQL Server
CPU is very important, and config Maxdop and Cost threshold for parallelism are affected to your result.
and many things related to cpu ...
The Other important factor you have to check is memory , are your queries cash , limitation of memory and etc
and many things related to RAM ...
I/O is very important in different way you can look at :
One side is what your disk IOPS is ? Or how many VMDK you are? how you config Filegroups in Vmdks and ...
the other side is How many Page IO you need to do your work in each server (related to check execution paln and Statistics , i will explain it)
how do you config your Tempdb by how many files (it's can related to CPU) or where your TempDB is locate
how do you config your Log File How many VLF Generate What size of Log growing and ...
MDF/NDF File Config
how do you config your Data File growing ... , FileGroups and etc
Do you config Instant File Initialization
and many other reason of course ...
After ALL ...
It's very important to check you Execution Plan (DO NOT COMPARE COST , CHECK WITCH OPERAND USE) in each server and how many page IO you need to complete your action.
check your statistics are update.
when you want to compare some scenario like yours, has baseline is very helpfull to get correct result ,test your senarios a lot and find a baseline to compare
Finally when you use Non-Cluster instead of Cluster Index
if i want to explain shortly : Cluster Index is structure of your data (actually is your data in B+Tree ...) when you remove it your table now is Heap and don't have Tree structure and don't need to sort , or other IO need , for this reason and many other reasons ... your bulk insert faster than before